package handlers

import (
	"encoding/json"
	"restaurant-system/config"
	"restaurant-system/internal/models"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

type OrderItemRequest struct {
	DishID   uint    `json:"dish_id" binding:"required"`
	Quantity int     `json:"quantity" binding:"required"`
	Price    float64 `json:"price" binding:"required"`
}

type CreateOrderRequest struct {
	OrderType string             `json:"order_type" binding:"required"` // 堂食/外卖
	Address   string             `json:"address"`
	Phone     string             `json:"phone"`
	Items     []OrderItemRequest `json:"items" binding:"required"`
}

// 创建订单
func CreateOrder(c *gin.Context) {
	userID, _ := c.Get("userID")
	var req CreateOrderRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	// 计算订单总金额
	var totalAmount float64
	var orderItems []models.OrderItem
	for _, item := range req.Items {
		// 检查库存
		var dish models.Dish
		if err := config.DB.First(&dish, item.DishID).Error; err != nil {
			c.JSON(400, gin.H{"error": "菜品不存在"})
			return
		}
		if dish.Stock < item.Quantity {
			c.JSON(400, gin.H{"error": "库存不足"})
			return
		}

		subtotal := item.Price * float64(item.Quantity)
		totalAmount += subtotal

		orderItems = append(orderItems, models.OrderItem{
			DishID:   item.DishID,
			Quantity: item.Quantity,
			Price:    item.Price,
			Subtotal: subtotal,
		})

		// 更新库存
		dish.Stock -= item.Quantity
		config.DB.Save(&dish)
	}

	// 创建订单
	order := models.Order{
		UserID:      userID.(uint),
		TotalAmount: totalAmount,
		OrderType:   req.OrderType,
		Address:     req.Address,
		Phone:       req.Phone,
		Status:      "pending",
		Items:       orderItems,
	}

	if err := config.DB.Create(&order).Error; err != nil {
		c.JSON(500, gin.H{"error": "创建订单失败"})
		return
	}

	if err := UpdateOrderStats(userID.(uint), order); err != nil {
		c.JSON(500, gin.H{"error": "更新订单统计失败"})
		return
	}

	c.JSON(200, gin.H{"message": "创建订单成功", "order": order})
}

// 获取订单列表
func GetOrders(c *gin.Context) {
	userID, _ := c.Get("userID")

	// 获取分页参数
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))

	var total int64
	var orders []models.Order

	// 获取总数
	if err := config.DB.Model(&models.Order{}).Where("user_id = ?", userID).Count(&total).Error; err != nil {
		c.JSON(500, gin.H{"error": "获取订单总数失败"})
		return
	}

	// 一次性加载所有需要的数据
	if err := config.DB.
		Preload("Items").
		Preload("Items.Dish", func(db *gorm.DB) *gorm.DB {
			return db.Select("id, name, image_url, price, description")
		}).
		Where("user_id = ?", userID).
		Order("created_at desc").
		Offset((page - 1) * pageSize).
		Limit(pageSize).
		Find(&orders).Error; err != nil {
		c.JSON(500, gin.H{"error": "获取订单失败: " + err.Error()})
		return
	}

	// 查询每个订单的评价状态
	for i := range orders {
		var reviewCount int64
		if err := config.DB.Model(&models.Review{}).
			Where("order_id = ?", orders[i].ID).
			Count(&reviewCount).Error; err != nil {
			continue
		}
		orders[i].IsReviewed = reviewCount == int64(len(orders[i].Items))
	}

	c.JSON(200, gin.H{
		"orders":   orders,
		"total":    total,
		"page":     page,
		"pageSize": pageSize,
	})
}

// 获取订单详情
func GetOrder(c *gin.Context) {
	userID, _ := c.Get("userID")
	id := c.Param("id")
	var order models.Order

	// 修改查询，预加载订单项、菜品和评价信息
	if err := config.DB.
		Preload("Items").
		Preload("Items.Dish").
		Preload("Items.Review"). // 预加载每个订单项的评价
		Where("id = ? AND user_id = ?", id, userID).
		First(&order).Error; err != nil {
		c.JSON(404, gin.H{"error": "订单不存在"})
		return
	}

	// 检查订单是否已评价
	var reviewCount int64
	if err := config.DB.Model(&models.Review{}).
		Where("order_id = ?", order.ID).
		Count(&reviewCount).Error; err != nil {
		c.JSON(500, gin.H{"error": "检查评价状态失败"})
		return
	}
	order.IsReviewed = reviewCount == int64(len(order.Items))

	// 处理评价中的图片字段
	for i := range order.Items {
		if order.Items[i].Review.ID != 0 { // 如果有评价
			var images []string
			json.Unmarshal([]byte(order.Items[i].Review.Images), &images)
			imagesJSON, _ := json.Marshal(images)
			order.Items[i].Review.Images = string(imagesJSON)
		}
	}

	c.JSON(200, gin.H{"order": order})
}

// 更新订单状态
func UpdateOrderStatus(c *gin.Context) {
	userID, _ := c.Get("userID")
	id := c.Param("id")
	var req struct {
		Status string `json:"status" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	// 先获取订单信息
	var order models.Order
	if err := config.DB.First(&order, id).Error; err != nil {
		c.JSON(404, gin.H{"error": "订单不存在"})
		return
	}

	// 验证订单是否属于当前用户
	if order.UserID != userID.(uint) {
		c.JSON(403, gin.H{"error": "无权操作此订单"})
		return
	}

	// 更新订单状态
	if err := config.DB.Model(&order).Update("status", req.Status).Error; err != nil {
		c.JSON(500, gin.H{"error": "更新订单状态失败"})
		return
	}

	// 如果订单状态变更为完成，则增加积分
	if req.Status == "completed" {
		// 订单完成时增加积分
		if err := AddOrderPoints(order.ID, userID.(uint), order.TotalAmount); err != nil {
			c.JSON(500, gin.H{"error": "增加积分失败"})
			return
		}
	}

	c.JSON(200, gin.H{"message": "更新订单状态成功"})
}

// 管理员获取所有订单
func GetAllOrders(c *gin.Context) {
	// 获取分页参数
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))

	var total int64
	var orders []models.Order

	// 获取总数
	if err := config.DB.Model(&models.Order{}).Count(&total).Error; err != nil {
		c.JSON(500, gin.H{"error": "获取订单总数失败"})
		return
	}

	// 使用 Preload 预加载订单项、菜品和用户信息
	if err := config.DB.
		Preload("Items").
		Preload("Items.Dish", func(db *gorm.DB) *gorm.DB {
			return db.Select("id, name, image_url, price, description, category")
		}).
		Preload("User").
		Order("created_at desc").
		Offset((page - 1) * pageSize).
		Limit(pageSize).
		Find(&orders).Error; err != nil {
		c.JSON(500, gin.H{"error": "获取订单列表失败"})
		return
	}

	c.JSON(200, gin.H{
		"orders":   orders,
		"total":    total,
		"page":     page,
		"pageSize": pageSize,
	})
}

// 管理员获取订单详情
func GetOrderByAdmin(c *gin.Context) {
	id := c.Param("id")
	var order models.Order

	// 使用 Preload 预加载订单项和用户信息
	if err := config.DB.Preload("Items").Preload("User").First(&order, id).Error; err != nil {
		c.JSON(404, gin.H{"error": "订单不存在"})
		return
	}

	c.JSON(200, gin.H{"order": order})
}

// 管理员更新订单状态
func UpdateOrderStatusByAdmin(c *gin.Context) {
	id := c.Param("id")
	var req struct {
		Status string `json:"status" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	// 先获取订单信息
	var order models.Order
	if err := config.DB.First(&order, id).Error; err != nil {
		c.JSON(404, gin.H{"error": "订单不存在"})
		return
	}

	// 验证状态变更是否合法
	validStatus := map[string]bool{
		"pending":    true,
		"processing": true,
		"completed":  true,
		"cancelled":  true,
	}

	if !validStatus[req.Status] {
		c.JSON(400, gin.H{"error": "无效的订单状态"})
		return
	}

	// 更新订单状态
	if err := config.DB.Model(&order).Update("status", req.Status).Error; err != nil {
		c.JSON(500, gin.H{"error": "更新订单状态失败"})
		return
	}

	// // 如果订单状态变更为完成，则增加积分
	// if req.Status == "completed" {
	// 	if err := AddOrderPoints(order.ID, order.UserID, order.TotalAmount); err != nil {
	// 		c.JSON(500, gin.H{"error": "增加积分失败"})
	// 		return
	// 	}
	// }

	c.JSON(200, gin.H{"message": "更新订单状态成功"})
}

// GetUserOrders 获取指定用户的订单列表
func GetUserOrders(c *gin.Context) {
	userID := c.Param("userId")

	var orders []models.Order
	if err := config.DB.
		Preload("Items.Dish").
		Where("user_id = ?", userID).
		Order("created_at desc").
		Find(&orders).Error; err != nil {
		c.JSON(500, gin.H{"error": "获取订单失败"})
		return
	}

	type OrderItemResponse struct {
		ID       uint    `json:"id"`
		DishName string  `json:"dish_name"`
		Price    float64 `json:"price"`
		Quantity int     `json:"quantity"`
	}

	type OrderResponse struct {
		OrderID     uint                `json:"order_id"`
		CreatedAt   time.Time           `json:"created_at"`
		Status      string              `json:"status"`
		TotalAmount float64             `json:"total_amount"`
		Items       []OrderItemResponse `json:"items"`
	}

	var response []OrderResponse
	for _, order := range orders {
		var items []OrderItemResponse
		for _, item := range order.Items {
			items = append(items, OrderItemResponse{
				ID:       item.ID,
				DishName: item.Dish.Name,
				Price:    item.Price,
				Quantity: item.Quantity,
			})
		}

		response = append(response, OrderResponse{
			OrderID:     order.ID,
			CreatedAt:   order.CreatedAt,
			Status:      order.Status,
			TotalAmount: order.TotalAmount,
			Items:       items,
		})
	}

	c.JSON(200, gin.H{"orders": response})
}
